// File: Conditions.h

//####################################################
//################# Condition System #################
//####################################################

extern void*	HandlerChains;
extern short	CountHandlerChains;

struct Condition
{
	virtual void DefaultHandler(void) { }
	
 public:

	static void Signal(Condition& cond);
	
	void Signal(void) { Signal(*this); }
};


enum HandlerChainKind
{
	hCondition
};

template <HandlerChainKind KIND>
struct PrimHandler
{
//	static PrimHandler& root;
	
	struct RecentHandler
	{
		PrimHandler&	recent;
		RecentHandler(PrimHandler& r) : recent(r) { }
	};
	
	static struct LinkedRecentHandler : RecentHandler
	{
		LinkedRecentHandler(PrimHandler& r) : RecentHandler(r), previousChain(GetPreviousChain()) { }
		RecentHandler& operator = (RecentHandler& rhs) { *static_cast<RecentHandler*>(this) = rhs; return *this; }
		
	 private:
		void*	previousChain;
		void* GetPreviousChain(void);
	}		chain;
	
	PrimHandler&	previous;

	PrimHandler(void) : previous(chain.recent) { chain = RecentHandler(*this); }
	~PrimHandler(void) { chain = RecentHandler(previous); }
};

struct PrimConditionHandler : PrimHandler<hCondition>
{
	typedef bool (PrimConditionHandler::*tester)(Condition& cond);
	typedef bool (PrimConditionHandler::*actor)(Condition& cond);
	
	PrimConditionHandler::tester	test;
	PrimConditionHandler::actor	act;
	
	PrimConditionHandler(tester t = NULL) : test(t), act(&PrimConditionHandler::Act) { }
	PrimConditionHandler(actor a, tester t) : test(t), act(a) { }
	
	virtual bool Applies(Condition& cond) = 0;

	bool Act(Condition& cond)
	{
		return false;
	}
	
	static PrimConditionHandler* GetRecent(void) { return &static_cast<PrimConditionHandler&>(PrimHandler<hCondition>::chain.recent); }
	PrimConditionHandler* GetNext(void) { return &static_cast<PrimConditionHandler&>(previous); }
};


template <class COND>
struct ConditionHandler : PrimConditionHandler
{
	ConditionHandler(tester t = NULL) : PrimConditionHandler(t) { }
	ConditionHandler(actor a, tester t) : PrimConditionHandler(a, t) { }
	
	virtual bool Applies(Condition& cond)
	{
		COND* condi(dynamic_cast<COND*>(&cond));
		return condi && (test == NULL || (this->*test)(cond));
	}
	
	typedef COND HandlingCondition;
};


//#########################################
//################# Query #################
//#########################################


template <bool EXP>
class Query : public Condition
{
	bool	result;

 public:
	
	Query(void) : result(EXP) { }
	operator bool(void) { return result; }
	void Set(bool r) { result = r; }
};


//##########################################
//################# Getter #################
//##########################################

template <class INFO, class BASE = Condition>
class GetterCondition : public BASE
{
	mutable INFO*	info;
 public:
	GetterCondition(bool sig = true) : info(NULL) { if (sig) Signal(); }
	operator INFO&(void) { return *info; }
	void operator = (INFO& i) const { info = &i; }
	private: virtual void DefaultHandler(void) { Debugger(); }
};



//###########################################
//################# Restart #################
//###########################################

class Restart : Condition
{

};


//###############################################
//################# RootHandler #################
//###############################################

struct RootHandler : ConditionHandler<Condition>
{
	RootHandler(void) : ConditionHandler<Condition>(static_cast<actor>(&RootHandler::LastResort), NULL) { }
	bool LastResort(Condition& cond) { cond.DefaultHandler(); return true; }
};

extern RootHandler RootConditionHandler;


